#pragma once
#include"nocopy.hpp"
#include"Log.hpp"
#include<iostream>
#include<string>
#include<sys/types.h>
#include<sys/socket.h>
#include<cerrno>
#include<cstring>
#include<unistd.h>
#include"Comm.hpp"
#include<netinet/in.h>
#include<strings.h>
 #include <arpa/inet.h>
using namespace std;

Log lg;

static const string defaultip="0.0.0.0";
static const uint16_t defaultport=8888;
static const int defaultfd=-1;
static const int defaultsize=1024;

class UdpServer:public nocopy
{
    public:
    UdpServer(string ip=defaultip,uint16_t port=defaultport)
    :_ip(ip),_port(port),_sockfd(defaultfd)
    {}
    void Init()
    {
        //创建套接字
        _sockfd=socket(AF_INET,SOCK_DGRAM,0);
        if(_sockfd<0)
        {
            lg.LogMessage(Fatal,"socket error,%d :%s\n",errno,strerror(errno));
            exit(Socket_Err);
        }
        lg.LogMessage(Info,"socket success ,sockfd:%d \n",_sockfd);

        //2.绑定，指定网络信息
        struct sockaddr_in local;//创建套接字地址结构体对象
        bzero(&local,sizeof(local));//初始化local
        local.sin_family=AF_INET;//指定协议族
        local.sin_port=htons(_port);//指定端口号（htons的功能就是将我们创建的端口号转成网络子节序）
        local.sin_addr.s_addr=inet_addr(_ip.c_str()); //指定ip，需要传递整形的ip（inet_addr就是将字符串ip地址转为整形，同时也转为网络子节序）
        int n=::bind(_sockfd,(struct sockaddr *)&local,sizeof(local));//将套接字地址结构体绑定到套接字
        if(n!=0)
        {
            lg.LogMessage(Fatal,"bind err ,%d:%s",errno,strerror(errno));
            exit(Bind_Err);
        }
    }
    void Start()
    {
        //服务器永远是在循环运行
        char buffer[defaultsize];//创建一个缓冲区
        for(;;)
        {
            struct sockaddr_in peer;//创建一个套接字地址空间，用于存储客户端的套接字地址
            socklen_t len=sizeof(peer);//获取套接字的地址空间大小
            ssize_t n=recvfrom(_sockfd,buffer,sizeof(buffer)-1,0,(struct sockaddr*)&peer,&len);//用于接收来自客户端的数据，并将其存储在buffer中
            if(n>0)
            {
                buffer[n]=0;
                cout<<"client say#"<<buffer<<"#"<<endl;
                sendto(_sockfd,buffer,strlen(buffer),0,(struct sockaddr* )&peer,len);//向指定的套接字peer进行接收数据
            }
        }
    }

    ~UdpServer()
    {}
    private:
        string _ip;
        uint16_t _port;
        int _sockfd;
};
